package com.knightboy.smartshoes.coreUtil;

import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * Created by knightBoy on 2015/7/24.
 */

public class SenserData {

    private final static String TAG = "data";

    //重力加速度
    static final double GRAVITY = 9.8;

    //是否正在室内导航的标志
    static boolean isNavi = false;
    //是否摔倒的标记，供报警时使用
    static boolean isfallen = false;
    //是否需要提醒的标记
    static boolean hasAwake = false;
    //修改室内导航界面的Handler类
    static Handler mHandler;
    //摔倒信息传送的Handler类
    static Handler fallOrBreakHandler;
    //判断计步的参数，方便随时改
    static int acceleration = 130;
    static int palstance = 25;

    //最终得到的数据类
    static class EndData{
        static double x_acceleration, y_acceleration, z_acceleration,     //加速度
                x_palstance, y_palstance, z_palstance,                    //角速度
                x_angle,    y_angle,      z_angle,                        //角度
                x_magnetic, y_magnetic,   z_magnetic,                     //磁场
                pressue1,   pressue2;                                     //压力值
        static int rssi;
        static double avg_acceleration;                                  //加速度的平均值
    }

    /**
     * 设置rssi
     * @param rssi
     */
    public static void setRssi(int rssi){
        EndData.rssi = rssi;
    }

    public static void reset(){
        EndData.x_acceleration = EndData.y_acceleration = EndData.z_acceleration = 0;
        EndData.x_palstance = EndData.y_palstance = EndData.z_palstance = 0;
        EndData.x_angle = EndData.y_angle = EndData.z_angle = 0;
        EndData.x_magnetic = EndData.y_magnetic =EndData.z_magnetic = 0;
        EndData.pressue1 = EndData.pressue2 = 0;
    }

    /**
     * 获得压力值，供上传服务器使用
     * @return
     */
    public static double getPressure1(){
        return EndData.pressue1;
    }
    public static double getPressure2(){
        return EndData.pressue2;
    }

    //获得加速度和
    public static int getAcceleration(){
        return acceleration;
    }
    //获得x角速度
    public static int getPalstance(){
        return palstance;
    }

    /**
     * 获得是否摔倒标志
     * @return
     */
    public static boolean getIsFallen(){
        return isfallen;
    }

    public static void setAcceleration(int aAcceleration){
        acceleration = aAcceleration;
    }
    public static void setPalstance(int aPalstance){
        palstance = aPalstance;
    }

    /**
     * 设置摔倒标志
     * @param aIsfallen
     */
    public static void setIsfallen(boolean aIsfallen){
        isfallen = aIsfallen;
    }

    /**
     * 设置是否提醒标记
     * @param aHasAwake
     */
    public static void setHasAwake(boolean aHasAwake){
        hasAwake = aHasAwake;
    }

    /**
     * 设置是否在室内导航的标志位
     * @param naviOrNot
     */
    public static void setIsNavi(boolean naviOrNot){
        isNavi = naviOrNot;
    }

    /**
     * 设置处理室内导航的Handler对象
     * @param aHandler
     */
    public static void setInnerHandler(Handler aHandler){
        mHandler = aHandler;
    }

    /**
     * 设置处理行人摔倒Handler对象
     * @param mHandler
     */
    public static void setFallOrBreakHandler(Handler mHandler){
        fallOrBreakHandler = mHandler;
    }

    /**
     * 分析包含加速度的数据
     * @param data
     */
    public synchronized static void handleByteArray(byte[] data) throws InterruptedException {
        EndData.x_acceleration = (merge(data[1], data[2]))/32768.0*16*GRAVITY;
        EndData.y_acceleration = (merge(data[3], data[4]))/32768.0*16*GRAVITY;
        EndData.z_acceleration = (merge(data[5], data[6]))/32768.0*16*GRAVITY;
        EndData.x_palstance = (merge(data[7], data[8]))/32768.0*2000;
        EndData.y_palstance = (merge(data[9], data[10]))/32768.0*2000;
        EndData.z_palstance = (merge(data[11], data[12]))/32768.0*2000;
        EndData.x_magnetic = (merge(data[13], data[14]))/32768.0*180;
        EndData.y_magnetic = (merge(data[15], data[16]))/32768.0*180;
        EndData.z_magnetic = (merge(data[17], data[18]))/32768.0*180;

        //判断是否摔倒
        if(hasFall() == true){
            if(isfallen == false){
                //利用Handler通知首界面用户已摔倒
                Message message = new Message();
                message.arg1 = 1;
                fallOrBreakHandler.sendMessage(message);

                isfallen = true;
            }
        }else {
            isfallen = false;
        }

        //判断是否需要站起来运动一下
        if(SharedData.hasABreak(System.currentTimeMillis()) == true){
            if(hasAwake == false){
                //利用Handler通知界面提醒用户注意运动
                Message message = new Message();
                message.arg1 = 2;
                fallOrBreakHandler.sendMessage(message);

                hasAwake = true;
            }
        }

        //判断是否在走步
        boolean hasWalk = hasWalk(EndData.x_acceleration,EndData.y_acceleration,EndData.z_acceleration,EndData.x_palstance);
        if(hasWalk){
            DataHelper.countStep(Math.abs(EndData.x_acceleration), 1.135);
            //如果正在室内导航，要改变剩余路段长度
            if(isNavi == true){
                //给服务器发送位置数据，实时更新位置
                String urlStr = "http://1.kbdouni.sinaapp.com/shoes/uploadLoc.php?"
                        +"fromp=" + LocationHelper.getPoint(LocationHelper.fromPlace)
                        +"&top=" + LocationHelper.getPoint(LocationHelper.toPlace)
                        +"&axis=" + LocationHelper.axis
                        +"&length=" + (LocationHelper.distance-LocationHelper.remain);
                new UploadLocation().execute(urlStr);
                //减少路径上的未走过长度
                LocationHelper.reduceRemain(0.7);
                //如果到达了目的地
                if(LocationHelper.hasReach() == true){
                    //改变正在室内导航标志
                    setIsNavi(false);
                    //利用Handler通知导航界面
                    Message message = new Message();
                    message.arg1 = 0;
                    mHandler.sendMessage(message);
                }
            }
        }

        //获得平均加速度
        getAvgAcceleration(EndData.x_acceleration, EndData.y_acceleration, EndData.z_acceleration);
    }

    /**
     * 分析包含压力值的数据
     * @param data
     * @param isPressue
     */
    public synchronized static void handleByteArray(byte[] data, boolean isPressue){
        EndData.x_angle = (merge(data[1], data[2]))/32768.0*180;
        EndData.y_angle = (merge(data[3], data[4]))/32768.0*180;
        EndData.z_angle = (merge(data[5], data[6]))/32768.0*180;
        EndData.pressue1 = (merge(data[7], data[8]));
        EndData.pressue2 = (merge(data[9], data[10]));

        //更新压力数据
        DataHelper.setTwoStress(EndData.pressue1, EndData.pressue2);
    }

    /**
     * 两个字节的合并成一个整数，aByte为高字节
     * @param aByte
     * @param bByte
     * @return
     */
    private static short merge(byte aByte, byte bByte){
        //value是16位的
        short value = 0;
        //aByte作为低八位
        short s0 = (short) (aByte & 0xff);
        short s1 = (short) (bByte & 0xff);
        s1 <<= 8;
        value = (short)(s1 | s0);
        return value;
    }

    /**
     * 判断是否走步的算法
     * @param x x轴加速度
     * @param y y轴加速度
     * @param z z轴加速度
     * @param w x轴角速度
     * @return 返回真表示走过一步
     */
    private static boolean hasWalk(double x, double y, double z, double w){
        boolean result = false;
        //得到三个轴加速度模平方和
        double r = Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2);
        Log.e(TAG,w+"");
        //判定条件
        if(!(85<r && r<acceleration && (0-palstance)<w && w<palstance)){
                result = true;
        }
        return result;
    }

    /**
     * 在判定走一步之后，由本次加速度三个值，结合上次加速度平均值，计算新的加速度平均值
     * @param x_acceleration 新的x轴加速度
     * @param y_acceleration
     * @param z_acceleration
     * @return
     */
    private static double getAvgAcceleration(double x_acceleration,double y_acceleration,double z_acceleration){
        double avg_acceleration = EndData.avg_acceleration;

        double sum = Math.pow(x_acceleration, 2) + Math.pow(y_acceleration, 2) + Math.pow(z_acceleration, 2);
        double sqrt = Math.sqrt(sum);
        avg_acceleration = (avg_acceleration + sqrt)/2.0;

        return avg_acceleration;
    }

    /**
     * 判断是否摔倒
     * @return
     */
    public static boolean hasFall(){
        double x_angle = Math.abs(EndData.x_angle);
        double y_angle = Math.abs(EndData.y_angle);
        double x_palstance = Math.abs(EndData.x_palstance);
        double y_palstance = Math.abs(EndData.y_palstance);
        double z_palstance = Math.abs(EndData.z_palstance);
        if(x_angle>70 || y_angle>70) {
            return true;
        }else {
            return false;
        }
    }

    public static String getData(){
        String result = "";

        result +=
//                "X:" + EndData.x_acceleration + "\n" +
//                "Y:" + EndData.y_acceleration + "\n" +
//                "Z:" + EndData.z_acceleration + "\n\n" +
//
//                "X:" + EndData.x_angle + "\n" +
//                "Y:" + EndData.y_angle + "\n" +
//                "Z:" + EndData.z_angle + "\n\n" +
//                "X:" + EndData.x_palstance + "\n" +
//                "Y:" + EndData.y_palstance + "\n" +
//                "Z:" + EndData.z_palstance;
//
//                "X:" + EndData.x_magnetic + "\n" +
//                "Y:" + EndData.y_magnetic + "\n" +
//                "Z:" + EndData.z_magnetic + "\n\n" +
//
                "RSSI:" + EndData.rssi + "\n";
//                "压力1:" + EndData.pressue1 + "\n" +
//                "压力2:" + EndData.pressue2*0.1191 + "\n\n";
        return result;
    }
}
